/*
Copyright [2020] [https://www.xiaonuo.vip]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：

1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Snowy源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处，作者声明等。
4.分发源码时候，请注明软件出处 https://gitee.com/xiaonuobase/snowy
5.在修改包名，模块名称，项目代码等时，请注明软件出处 https://gitee.com/xiaonuobase/snowy
6.若您的项目无法满足以上几点，可申请商业授权，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.modular.manage.poidata.service.impl;

import cc.blynk.clickhouse.ClickHouseConnection;
import cc.blynk.clickhouse.ClickHouseDataSource;
import cc.blynk.clickhouse.ClickHouseStatement;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.log.Log;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import vip.xiaonuo.core.dbs.CurrentDataSourceContext;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.core.factory.PageFactory;
import vip.xiaonuo.core.pojo.page.PageResult;
import vip.xiaonuo.core.util.PoiUtil;
import vip.xiaonuo.dbs.core.annotation.DataSource;
import vip.xiaonuo.modular.common.DistanceHelper;
import vip.xiaonuo.modular.common.LoadClickhouseDatasource;
import vip.xiaonuo.modular.common.WdAnalysisConst;
import vip.xiaonuo.modular.manage.biCountryProfile.entity.BiCountryProfile;
import vip.xiaonuo.modular.manage.biCountryProfile.service.BiCountryProfileService;
import vip.xiaonuo.modular.manage.biindexdata.entity.BiIndexData;
import vip.xiaonuo.modular.manage.biindexdata.mapper.BiIndexDataMapper;
import vip.xiaonuo.modular.cache.PoiDataTagsTypeCache;
import vip.xiaonuo.modular.manage.poidata.entity.BiPoiData;
import vip.xiaonuo.modular.manage.poidata.entity.PoiData;
import vip.xiaonuo.modular.manage.poidata.entity.SubTagTotal;
import vip.xiaonuo.modular.manage.poidata.enums.PoiDataExceptionEnum;
import vip.xiaonuo.modular.manage.poidata.mapper.BiPoiDataMapper;
import vip.xiaonuo.modular.manage.poidata.mapper.PoiDataMapper;
import vip.xiaonuo.modular.manage.poidata.param.PoiDataParam;
import vip.xiaonuo.modular.manage.poidata.service.PoiDataService;
import vip.xiaonuo.modular.manage.poidatatags.entity.PoiDataTags;
import vip.xiaonuo.modular.manage.poidatatags.mapper.PoiDataTagsJoinTypeMapper;
import vip.xiaonuo.modular.manage.poidatatags.mapper.PoiDataTagsMapper;
import vip.xiaonuo.sys.modular.area.entity.SysArea;
import vip.xiaonuo.sys.modular.area.service.SysAreaService;
import vip.xiaonuo.util.GenerateUniqueIdUtil;

import javax.annotation.Resource;
import java.io.*;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.stream.Collectors;

/**
 * POI数据service接口实现类
 *
 * @author cy
 * @date 2022-07-28 19:28:29
 */
@Service
public class PoiDataServiceImpl extends ServiceImpl<PoiDataMapper, PoiData> implements PoiDataService {

    Log log = Log.get();

    @Resource
    private BiPoiDataMapper biPoiDataMapper;
    @Resource
    private BiIndexDataMapper biIndexDataMapper;
    @Resource
    private PoiDataTagsMapper poiDataTagsMapper;

    @Resource
    private SysAreaService sysAreaService;

    @Resource
    private BiCountryProfileService biCountryProfileService;

    @Resource
    private PoiDataTagsJoinTypeMapper poiDataTagsJoinTypeMapper;

    @Resource
    private  PoiDataTagsTypeCache poiDataTagsTypeCache;

    /**
     * 查詢区域画像，先在中间表查询，如果没有，则调用计算逻辑回写到中间表
     * @param poiDataParam
     * @return
     */
    public Map queryImageType(PoiDataParam poiDataParam){
        LambdaQueryWrapper<BiCountryProfile> wrapper = new LambdaQueryWrapper<>();

        if (StringUtils.isEmpty(poiDataParam.getGrid())) {
            throw new ServiceException(9,"网格编号不能为空");
        }
        wrapper.eq(BiCountryProfile::getGrid,poiDataParam.getGrid());


        if (poiDataParam.getYear() != null) {
            wrapper.eq(BiCountryProfile::getYear,poiDataParam.getYear());
        }
        if (StringUtils.hasText(poiDataParam.getProvName())) {
            wrapper.eq(BiCountryProfile::getProvName,poiDataParam.getProvName());
        }

        if (StringUtils.hasText(poiDataParam.getCityName())) {
            wrapper.eq(BiCountryProfile::getCityName,poiDataParam.getCityName());
        }
        if (StringUtils.hasText(poiDataParam.getCountryName())) {
            wrapper.eq(BiCountryProfile::getCountryName,poiDataParam.getCountryName());
        }
        wrapper.last(" limit 1 ");
        BiCountryProfile one = biCountryProfileService.getOne(wrapper);
        if (one != null) {
            return JSONObject.parseObject(one.getData());
        }
        else{
            String key = poiDataParam.getProvName()+poiDataParam.getCityName()+ poiDataParam.getCountryName()
                    +poiDataParam.getGrid();
            if(poiDataTagsTypeCache.get(key) == null) {
                poiDataTagsTypeCache.put(key,new JSONObject()); //防止重复计算
                HashMap<String, Double> map = calculateImageType(poiDataParam);
                return map;
            }
        }
        return new HashMap();
    }

    /**
     * 计算某个区域的画像信息
     * 返回HashMap(标签类型类型值：比例)
     * @param poiDataParam
     */
    public HashMap<String,Double> calculateImageType(PoiDataParam poiDataParam){
        String key = poiDataParam.getProvName()+poiDataParam.getCityName()+ poiDataParam.getCountryName()
                +poiDataParam.getGrid();
        // 查询某个区域的中类标签及比例 （比例=数量/总数）
        CurrentDataSourceContext.setDataSourceType(WdAnalysisConst.CLICKHOUSE_DATASOURCE);
        List<SubTagTotal> dataList = null;
        try {
            if (StringUtils.hasText(poiDataParam.getGrid())) {
                LambdaQueryWrapper<BiIndexData> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(BiIndexData::getGrid,poiDataParam.getGrid());
                wrapper.last(" limit 1 ");
                BiIndexData biIndexData = biIndexDataMapper.selectOne(wrapper);
                if(biIndexData == null){
                    throw new RuntimeException("没有找到网格数据："+poiDataParam.getGrid());
                }
                // 如果查询的是网格数据，则需要将网格编号转换成经纬度，扩大范围0.01
                String[] polygon = DistanceHelper.getNearbyDistance(new BigDecimal(biIndexData.getLng()), new BigDecimal(biIndexData.getLat()), 1);
                poiDataParam.setLng1(Double.parseDouble(polygon[0]));
                poiDataParam.setLng2(Double.parseDouble(polygon[1]));
                poiDataParam.setLat1(Double.parseDouble(polygon[2]));
                poiDataParam.setLat2(Double.parseDouble(polygon[3]));
//                poiDataParam.setLat(Double.parseDouble(biIndexData.getLat()));
//                poiDataParam.setLng(Double.parseDouble(biIndexData.getLng()));
            }
            dataList = biPoiDataMapper.groupBySubTag(poiDataParam);
        } catch (Exception e) {
            log.error("clickhouse查询出现错误：",e);
        }
        CurrentDataSourceContext.clearDataSourceType();
        if(CollectionUtil.isEmpty(dataList)){
            return new HashMap();
        }

        long sum = dataList.stream().mapToLong(t -> t.getTotal()).sum();
        HashMap<String, Double> doubleHashMap = new HashMap<>();
        dataList.forEach(el->{
            doubleHashMap.put(el.getSubTag(), (el.getTotal()+0D)/sum);
        });

        // 循环中类标签 找到这个中类标签 配置的 多个标签类型 放到Map中(相同标签类型累加)
        HashMap<String, Double> calcMap = new HashMap<>();
        doubleHashMap.forEach((tagsName,val)->{
            List<String> typeValueList = poiDataTagsJoinTypeMapper.selectTypeValueByTagsName(tagsName);
            if(CollectionUtil.isNotEmpty(typeValueList)){
                typeValueList.forEach(typeValue ->{
                    Double aDouble = calcMap.get(typeValue);
                    if (aDouble != null) {
                        aDouble += val;
                    }else{
                        aDouble = val;
                    }
                    calcMap.put(typeValue, aDouble);
                });
            }
        });
        HashMap<String, Double> result = new HashMap<>();
        calcMap.forEach((k,v)->{
            if(v>0.2){
                result.put(k, new BigDecimal(v).setScale(4,4).doubleValue());
            }
        });
        saveCountryProfile(poiDataParam,result);

        //计算完成，删除缓存标志
        poiDataTagsTypeCache.remove(key);
        return result;
    }

    /**
     * 保存画像结果到中间表  bi_country_profile
     * @param poiDataParam
     * @param result
     */
    public void saveCountryProfile(PoiDataParam poiDataParam,HashMap<String, Double> result){
        BiCountryProfile biCountryProfile = new BiCountryProfile();
        biCountryProfile.setYear(poiDataParam.getYear());
        biCountryProfile.setProvName(poiDataParam.getProvName());
        biCountryProfile.setCityName(poiDataParam.getCityName());
        biCountryProfile.setCountryName(poiDataParam.getCountryName());
        biCountryProfile.setGrid(poiDataParam.getGrid());
        biCountryProfile.setData(JSONObject.toJSONString(result));
        biCountryProfileService.save(biCountryProfile);
    }


    @Override
    public PageResult<BiPoiData> page(PoiDataParam poiDataParam) {
        return this.page(poiDataParam,PageFactory.defaultPage());
    }

    @Override
    public PageResult<BiPoiData> page(PoiDataParam poiDataParam,Page page) {
        QueryWrapper<BiPoiData> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(poiDataParam)) {
            if (ObjectUtil.isNotEmpty(poiDataParam.getName())) {
                queryWrapper.lambda().like(BiPoiData::getName,poiDataParam.getName());
            }
            if (ObjectUtil.isNotEmpty(poiDataParam.getAddress())) {
                queryWrapper.lambda().like(BiPoiData::getAddress,poiDataParam.getAddress());
            }
            if (ObjectUtil.isNotEmpty(poiDataParam.getProCode())) {
                SysArea sysArea = sysAreaService.lambdaQuery()
                        .eq(SysArea::getAreaCode,poiDataParam.getProCode()).one();
                queryWrapper.lambda().eq(BiPoiData::getProvName,sysArea.getName());
            }else if (ObjectUtil.isNotEmpty(poiDataParam.getProvName())) {
                queryWrapper.lambda().eq(BiPoiData::getProvName,poiDataParam.getProvName());
            }
            if (ObjectUtil.isNotEmpty(poiDataParam.getCitCode())) {
                SysArea sysArea = sysAreaService.lambdaQuery()
                        .eq(SysArea::getAreaCode,poiDataParam.getCitCode()).one();
                queryWrapper.lambda().eq(BiPoiData::getCityName,sysArea.getName());
            }else if (ObjectUtil.isNotEmpty(poiDataParam.getCityName())) {
                queryWrapper.lambda().eq(BiPoiData::getCityName,poiDataParam.getCityName());
            }
            if (ObjectUtil.isNotEmpty(poiDataParam.getRegCode())) {
                SysArea sysArea = sysAreaService.lambdaQuery()
                        .eq(SysArea::getAreaCode,poiDataParam.getRegCode()).one();
                queryWrapper.lambda().eq(BiPoiData::getCountryName,sysArea.getName());
            }else if (ObjectUtil.isNotEmpty(poiDataParam.getCountryName())) {
                queryWrapper.lambda().eq(BiPoiData::getCountryName,poiDataParam.getCountryName());
            }
            if (ObjectUtil.isNotEmpty(poiDataParam.getTag())) {
                queryWrapper.lambda().eq(BiPoiData::getTag,poiDataParam.getTag());
            }
            if (ObjectUtil.isNotEmpty(poiDataParam.getSubTag())) {
                queryWrapper.lambda().eq(BiPoiData::getSubTag,poiDataParam.getSubTag());
            } else if (CollectionUtil.isNotEmpty(poiDataParam.getSubTagIds())) {
                List<PoiDataTags> poiDataTags = poiDataTagsMapper.selectBatchIds(poiDataParam.getSubTagIds());
                List<String> collect = poiDataTags.stream().map(el -> el.getName()).collect(Collectors.toList());
                queryWrapper.lambda().in(BiPoiData::getSubTag,collect);

                List<Long> pids = poiDataTags.stream().map(el-> el.getParentId()).distinct().collect(Collectors.toList());
                List<PoiDataTags> pList = poiDataTagsMapper.selectBatchIds(pids);
                List<String> pNameList = pList.stream().map(el -> el.getName()).collect(Collectors.toList());
                queryWrapper.lambda().in(BiPoiData::getTag,pNameList);
            }

            if (ObjectUtil.isNotEmpty(poiDataParam.getYear())) {
                queryWrapper.lambda().eq(BiPoiData::getYear,poiDataParam.getYear());
            }
            if (poiDataParam.getLng() != 0) {
                queryWrapper.lambda().between(BiPoiData::getLng,poiDataParam.getLng()-0.1,poiDataParam.getLng()+0.1);
            }
            if (poiDataParam.getLat() != 0) {
                queryWrapper.lambda().between(BiPoiData::getLat,poiDataParam.getLat()-0.1,poiDataParam.getLat()+0.1);
            }
        }
        CurrentDataSourceContext.setDataSourceType(WdAnalysisConst.CLICKHOUSE_DATASOURCE);
        Page<BiPoiData> biPoiDataPage = biPoiDataMapper.selectPage(page, queryWrapper);
        CurrentDataSourceContext.clearDataSourceType();
        return new PageResult<>(biPoiDataPage);
    }

    /**
     * 检查是否已经导入，如果是，则重构表结构删除相同taskid的数据
     * @param taskId
     */
    public boolean checkAndDeleteByTaskId(String taskId) {
        boolean flag = false;
        CurrentDataSourceContext.setDataSourceType(WdAnalysisConst.CLICKHOUSE_DATASOURCE);
        QueryWrapper<BiPoiData> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(BiPoiData::getTaskId, taskId);
        long integer = biPoiDataMapper.selectCount(queryWrapper);
        if (integer > 0) {
//            biPoiDataMapper.deleteByTaskId(taskId);
            flag = true;
        }
        CurrentDataSourceContext.clearDataSourceType();
        return flag;
    }

    @Override
    public void allImport(String filepath, String year) {
        if (StringUtils.isEmpty(year)) {
            throw new ServiceException(9, "年份不能为空");
        }
        File path = new File(filepath);
        File[] files = path.listFiles();
        for (File f : files) {
            if (f.isDirectory()) {
                File[] subFiles = f.listFiles();
                for (File sf : subFiles) {
                    importData(year, sf.getName(), sf.getAbsolutePath());
                }
            }else{
                importData(year, f.getName(), f.getAbsolutePath());
            }
        }
        log.info("批量导入完成");
    }

    /**
     * 导入csv文件
     * @param taskId
     * @param file
     * @throws Exception
     */
    public void importData(String year,String taskId,String file) {
        File f = new File(file);
        if(!f.exists() || (!file.endsWith("csv"))){
            log.info("文件不存在或不是csv文件格式");
            return;
        }
        log.info("正在导入csv文件："+file);
        // 检查是否已经导入，如果是，则重构表结构删除相同taskid的数据
        boolean exist = checkAndDeleteByTaskId(taskId);
        if(exist){
            log.info("跳过csv文件："+file);
            return;
        }
        ClickHouseDataSource ds = LoadClickhouseDatasource.get();
        long startTime = System.currentTimeMillis();
        if (year == null) {
            year = String.valueOf(obtainYearByString(taskId));
        }
        int count = 0;
        InputStream is = null;
        try {
            ClickHouseConnection connection = ds.getConnection();
            ClickHouseStatement statement = connection.createStatement();

            is = new FileInputStream(file);
            Scanner scanner = new Scanner(is);
            StringBuffer data = new StringBuffer();
            int size = 0;
            int maxSize = 20000;
            //第一行的标题
            String[] titles = scanner.nextLine().split(",");
            StringBuffer query = new StringBuffer("insert into bi_poi_data (");
            HashMap<String, String> nameMap = new HashMap<>();
            nameMap.put("名称", "name");
            nameMap.put("大类", "tag");
            nameMap.put("中类", "sub_tag");
            nameMap.put("地址", "address");
            nameMap.put("经度", "lng");
            nameMap.put("纬度", "lat");
            nameMap.put("省份", "prov_name");
            nameMap.put("城市", "city_name");
            nameMap.put("区域", "country_name");
            for(String tit : titles){
                //名称,大类,中类,地址,经度,纬度,省份,城市,区域
                query.append(nameMap.get(tit)).append(",");
            }
            query.append("task_id,year,id) FORMAT CSV");
            while (scanner.hasNextLine()) {
                count++;
                if(data.length() > 1) data.append("\n");
                // 无量寿禅寺,旅游景点,宗教,迎宾路特1号,114.684021,29.411011,湖北省,咸宁市,通山县
                data.append(scanner.nextLine().replaceAll("'",""));
                // 增加taskid字段
                data.append(",").append(taskId);
                // 增加年份字段
                data.append(",").append(year);
                data.append(",").append(GenerateUniqueIdUtil.getGuid());
                size++;

                // 打包批量推送条件。
                if(size >= maxSize) {
                    InputStream dataStream = new ByteArrayInputStream(data.toString().getBytes());
                    statement.sendStreamSQL(dataStream, query.toString());
                    dataStream.close();
                    // 重置参数
                    size = 0;
                    data = new StringBuffer();
                }
            }
            scanner.close();
            // 剩余部分数据
            if(data.length() > 1) {
                InputStream dataStream = new ByteArrayInputStream(data.toString().getBytes());
                statement.sendStreamSQL(dataStream, query.toString());
                dataStream.close();
                // 重置参数
                size = 0;
                data = new StringBuffer();
            }
        } catch (Exception e) {
            log.error("poi文件导入失败：",e);
            throw new ServiceException(9,e.getMessage());
        }finally {
            try {
                is.close();
            } catch (IOException e) {
            }
        }
        log.info("总数据量："+count+" 用时："+(System.currentTimeMillis()-startTime));
    }

    private int obtainYearByString(String taskId) {
        for (int i = 1990; i <= 2030; i++) {
            if (taskId.contains(Integer.toString(i))) {
                return i;
            }
        }
        return 0;
    }

    @Override
    public List<PoiData> list(PoiDataParam poiDataParam) {
        return this.list();
    }

    public JSONObject customList(PoiDataParam poiDataParam) {
        if (ObjectUtil.isNotNull(poiDataParam)) {
            if (CollectionUtil.isNotEmpty(poiDataParam.getSubTagIds())) {
                List<PoiDataTags> poiDataTags = poiDataTagsMapper.selectBatchIds(poiDataParam.getSubTagIds());
                List<String> collect = poiDataTags.stream().map(el -> el.getName()).collect(Collectors.toList());
                poiDataParam.setSubTagNames(collect);

                List<Long> pids = poiDataTags.stream().map(el-> el.getParentId()).distinct().collect(Collectors.toList());
                List<PoiDataTags> pList = poiDataTagsMapper.selectBatchIds(pids);
                List<String> pNameList = pList.stream().map(el -> el.getName()).collect(Collectors.toList());
                poiDataParam.setTagNames(pNameList);
            }
            if(poiDataParam.getScale() != null){
                String sampleSQL = DistanceHelper.calcSampleSQL(poiDataParam.getScale(),10,15);
                poiDataParam.setSampleSQL(sampleSQL);
            }
        }
        Double lng1 = poiDataParam.getLng1();
        Double lng2 = poiDataParam.getLng2();
        Double lat1 = poiDataParam.getLat1();
        Double lat2 = poiDataParam.getLat2();
        if (lng1 != null && lat1 != null) {
            if(lng1.compareTo(lng2)>0){
                poiDataParam.setLng1(lng2);
                poiDataParam.setLng2(lng1);
            }
            if(lat1.compareTo(lat2)>0){
                poiDataParam.setLat1(lat2);
                poiDataParam.setLat2(lat1);
            }
        }
        this.trimLngLat(poiDataParam);
        String key = "poi"+JSONObject.toJSONString(poiDataParam);


        JSONObject cacheObject = poiDataTagsTypeCache.get(key);
        if(cacheObject != null){
            return cacheObject;
        }
        CurrentDataSourceContext.setDataSourceType(WdAnalysisConst.CLICKHOUSE_DATASOURCE);
        List<BiPoiData> biPoiData = biPoiDataMapper.customList(poiDataParam);
        CurrentDataSourceContext.clearDataSourceType();

        JSONObject result = new JSONObject();
        result.put("rows",biPoiData);
        poiDataTagsTypeCache.put(key,result);
        return result;
    }
    @Override
    public void add(PoiDataParam poiDataParam) {
        PoiData poiData = new PoiData();
        BeanUtil.copyProperties(poiDataParam, poiData);
        this.save(poiData);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<PoiDataParam> poiDataParamList) {
        poiDataParamList.forEach(poiDataParam -> {
            this.removeById(poiDataParam.getId());
        });
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(PoiDataParam poiDataParam) {
        PoiData poiData = this.queryPoiData(poiDataParam);
        BeanUtil.copyProperties(poiDataParam, poiData);
        this.updateById(poiData);
    }

    @Override
    public PoiData detail(PoiDataParam poiDataParam) {
        return this.queryPoiData(poiDataParam);
    }

    /**
     * 获取POI数据
     *
     * @author cy
     * @date 2022-07-28 19:28:29
     */
    private PoiData queryPoiData(PoiDataParam poiDataParam) {
        PoiData poiData = this.getById(poiDataParam.getId());
        if (ObjectUtil.isNull(poiData)) {
            throw new ServiceException(PoiDataExceptionEnum.NOT_EXIST);
        }
        return poiData;
    }

    @Override
    public void export(PoiDataParam poiDataParam) {
        List<BiPoiData> list =  this.page(poiDataParam,new Page<>(1, 5000)).getRows();
        PoiUtil.exportExcelWithStream("SnowyPoiData.xls", BiPoiData.class, list);
    }

    @Override
    @DataSource(name = WdAnalysisConst.CLICKHOUSE_DATASOURCE)
    public List<BiPoiData> findByTagName(List<String> list) {
        List<BiPoiData> byTagName = this.biPoiDataMapper.findByTagName(list);
        return byTagName;
    }

    /**
     * 经纬度保留两位小数、缩放比例保留1为小数
     * 方便建立缓存
     * @param param
     */
    private void trimLngLat(PoiDataParam param){
        if(param.getLat1() != null){
            if(!param.isExactLngLat()){
                param.setLat1(new BigDecimal(param.getLat1()).setScale(2,BigDecimal.ROUND_DOWN).doubleValue());
                param.setLat2(new BigDecimal(param.getLat2()).setScale(2,BigDecimal.ROUND_DOWN).doubleValue());
                param.setLng1(new BigDecimal(param.getLng1()).setScale(2,BigDecimal.ROUND_DOWN).doubleValue());
                param.setLng2(new BigDecimal(param.getLng2()).setScale(2,BigDecimal.ROUND_DOWN).doubleValue());
            }
        }
        if (param.getScale() != null) {
            double v = new BigDecimal(param.getScale()).setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();
            param.setScale(v);
        }
    }

}
